package com.lpb.spring.lpbspring.getway.helper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.lpb.spring.lpbspring.getway.model.GeneralModel;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

import static com.alibaba.fastjson.JSON.parseObject;
import static org.apache.commons.lang3.StringUtils.isBlank;

/**
 * FastJSON 操作辅助类
 */
public interface JSONHelper {

    static SerializeConfig getSerializeConfig(){
        SerializeConfig serializeConfig = new SerializeConfig();
        serializeConfig.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        serializeConfig.addFilter(GeneralModel.class, (PropertyFilter) (object, name, value) -> name.equals("id"));
        return serializeConfig;
    }

    /**
     * @param json
     * @param module a.b.c
     * @param type
     * @param <T>
     * @return
     */
    static <T> T getProperty(Object json, String module, Class<T> type) {
        T result = null;
        if (json != null && !"".equals(json) && (json instanceof JSONObject || json instanceof String)) {
            JSONObject settings = json instanceof JSONObject ? (JSONObject) json : parseObject(json.toString());
            String[] fields = module.split("\\.");
            for (int i = 0; i < fields.length; i++) {
                if (!settings.containsKey(fields[i])) {
                    break;
                }
                if (i < fields.length - 1) {
                    settings = settings.getJSONObject(fields[i]);
                } else {
                    result = settings.getObject(fields[i], type);
                }
            }
        }
        return result;
    }

    static String setProperty(String json, String module, Object value) {
        String result = json;
        if (StringUtils.isNotBlank(json)) {
            JSONObject settings = parseObjectOrdered(json);
            JSONObject prop = settings;
            String[] fields = module.split("\\.");
            for (int i = 0; i < fields.length; i++) {
                if (i < fields.length - 1) {
                    prop = prop.getJSONObject(fields[i]);
                } else {
                    prop.put(fields[i], value);
                }
            }
            result = settings.toJSONString();
        }
        return result;
    }

    static JSONObject parseObjectOrdered(String json) {
        return new JSONObject(parseObject(json, LinkedHashMap.class, Feature.OrderedField));
    }

    String EMPTY_OBJECT = "{}";
    String EMPTY_ARRAY = "[]";


    static JSONObject toJSONObject(Object object) {
        return (JSONObject) JSON.toJSON(object);
    }

    static JSONObject createObject(String keys, Object value) {
        JSONObject object = new JSONObject();
        String[] keyArray = keys.split("\\.");
        for(int i=keyArray.length - 1; i>=0; i--) {
            String key = keyArray[i];
            if(i == keyArray.length - 1) {
                object.put(key, value);
            } else {
                JSONObject parent = new JSONObject();
                parent.put(key, object);
                object = parent;
            }
        }
        return object;
    }

    static JSONArray toJSONArray(Object array) {
        return (JSONArray) JSON.toJSON(array);
    }

    static <T> List<T> toTypeArray(String arrayString, Class<T> tClass) {
        if(!arrayString.matches("^\\[.*\\]$")) {
            arrayString = JSON.toJSONString(arrayString.split(","));
        }
        return JSON.parseArray(arrayString, tClass);
    }

    static String stringify(Object obj) {
        return stringify(obj, false);
    }

    static String stringify(Object obj, boolean pretty) {
        return stringify(obj,null, 0,  pretty);
    }

    /**
     *
     * @param obj
     * @param properties
     * @param type -1：排除 其他：不处理 1：包含
     * @param pretty
     * @return
     */
    static String stringify(Object obj, String properties, final int type, boolean pretty) {
        final List<String> fields = isBlank(properties) ? new ArrayList<>() : Arrays.asList(properties.split(","));
        PropertyFilter propertyFilter = (object, name, value) -> ((type == -1) && !fields.contains(name)) || ((type == 1) && fields.contains(name));
        return pretty ? JSON.toJSONString(obj, propertyFilter, SerializerFeature.PrettyFormat) : JSON.toJSONString(obj, propertyFilter);
    }
}
